/**
 * Copyright 2019 吉鼎科技.
 *
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.engine.cmd.identity;

import cn.easyplatform.dao.EntityCallback;
import cn.easyplatform.dao.IdentityDao;
import cn.easyplatform.dos.OrgDo;
import cn.easyplatform.dos.UserDo;
import cn.easyplatform.entities.BaseEntity;
import cn.easyplatform.i18n.I18N;
import cn.easyplatform.interceptor.AbstractCommand;
import cn.easyplatform.interceptor.CommandContext;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.lang.Times;
import cn.easyplatform.messages.request.SimpleRequestMessage;
import cn.easyplatform.messages.response.LoginResponseMessage;
import cn.easyplatform.messages.response.SimpleResponseMessage;
import cn.easyplatform.messages.vos.AuthorizationVo;
import cn.easyplatform.messages.vos.OrgVo;
import cn.easyplatform.messages.vos.RoleVo;
import cn.easyplatform.services.ISubject;
import cn.easyplatform.type.IResponseMessage;
import cn.easyplatform.type.StateType;
import cn.easyplatform.log.LogManager;
import cn.easyplatform.util.IdentityUtils;
import cn.easyplatform.util.MessageUtils;
import cn.easyplatform.util.RuntimeUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

import static cn.easyplatform.type.UserType.TYPE_ADMIN;


/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class ConfirmCmd extends AbstractCommand<SimpleRequestMessage> {

    /**
     * @param req
     */
    public ConfirmCmd(SimpleRequestMessage req) {
        super(req);
    }

    @Override
    public IResponseMessage<?> execute(final CommandContext cc) {
        UserDo userInfo = (UserDo) cc.remove("TempUser");
        Boolean flag = (Boolean) req.getBody();
        if (flag) {// 确认
            //标示另外同名的用户为停止状态
            UserDo other = cc.getProjectService().getSessionManager().getUser(userInfo.getId());
            if (other != null) {
                other.setState(StateType.STOP);
                if (cc.getEngineConfiguration().getCacheManager().isCluster()) {
                    Subject subject = new Subject.Builder().sessionId(other.getSessionId()).buildSubject();
                    subject.getSession().setAttribute(CommandContext.USER_KEY, other);
                }
            }
            try {
                IdentityDao dao = cc.getIdentityDao(false);
                EntityCallback<BaseEntity> cb = new EntityCallback<BaseEntity>() {
                    @Override
                    public BaseEntity getEntity(String entityId) {
                        return cc.getEntity(entityId);
                    }

                    public String getLabel(String code) {
                        return RuntimeUtils.getLabel(cc, code, userInfo.getLocale());
                    }
                };
                if (!Strings.isBlank(cc.getProjectService().getConfig().getString("user.authentication.callback"))) {//执行登陆回调，例如针对特定的角色进行二次验证
                    List<RoleVo> roles = dao.getUserRoles(userInfo.getId(), cc.getEnv()
                            .getDeviceType().getName(), cb);
                    userInfo.setRoles(roles);
                    cc.setUser(userInfo);
                    IResponseMessage<?> resp = LoginCmd.doCallback(cc, cc.getProjectService().getConfig().getString("user.authentication.callback"));
                    if (!resp.isSuccess()) {
                        cc.logout();
                        return resp;
                    }
                    if (resp.getBody() instanceof String)
                        return resp;
                }
                int remainingDays = 0;
                Date now = Times.toDay();
                if (userInfo.getValidDays() > 0) {// 是否过期
                    int oneDay = 24 * 60 * 60 * 1000;
                    Date when = new Date(userInfo.getValidDate().getTime()
                            + userInfo.getValidDays() * oneDay);
                    int days = cc.getProjectService().getConfig().getDaysRemaining();
                    if (days > 0) {
                        remainingDays = (int) ((now.getTime() - when.getTime()) / oneDay);
                        if (remainingDays > days)// 如果剩余天数大于指定的天数，重置为零
                            remainingDays = 0;
                    }
                }
                userInfo.setLoginDate(new Date());
                userInfo.setLastAccessTime(new Date());
                if (userInfo.getType() == TYPE_ADMIN) {// 管理用户不需要去找机构
                    userInfo.setOrg(new OrgDo());
                    userInfo.getOrg().setId("admin");
                    userInfo.getOrg().setName("admin");
                    userInfo.getOrg().setExtraInfo(new HashMap<>());
                    List<RoleVo> roles = dao.getUserRoles(userInfo.getId(), cc.getEnv()
                            .getDeviceType().getName(), cb);
                    LoginResponseMessage resp = new LoginResponseMessage(
                            new AuthorizationVo(null, roles));
                    resp.setType(userInfo.getType());
                    resp.setName(userInfo.getName());
                    if (remainingDays > 0)
                        resp.setTooltip(I18N.getLabel("app.user.expiring", remainingDays));
                    userInfo.setState(StateType.START);
                    cc.setUser(userInfo);
                    cc.getSync().clear();
                    IdentityUtils.log(cc, dao);
                    LogManager.startUser(cc.getEngineConfiguration().getLogPath(), cc.getEnv().getId(), userInfo);
                    return resp;
                }
                List<OrgVo> orgs = dao.getUserOrgs(userInfo.getId(), cb);
                if (orgs.isEmpty())
                    return MessageUtils.userNotOrg(userInfo.getId());
                LoginResponseMessage resp = null;
                if (orgs.size() == 1) { // 默认的机构号
                    String orgId = orgs
                            .remove(0).getId();
                    AuthorizationVo av = IdentityUtils.getUserAuthorization(cc, userInfo, orgId);
                    resp = new LoginResponseMessage(av);
                    userInfo.setSessionId(req.getSessionId());
                    resp.setOrgId(orgId);
                    if (resp.isSuccess())
                        LogManager.startUser(cc.getEngineConfiguration().getLogPath(), cc.getEnv().getId(), userInfo);
                } else
                    // 由用户选择机构
                    resp = new LoginResponseMessage(orgs);
                resp.setType(userInfo.getType());
                resp.setName(userInfo.getName());
                cc.setUser(userInfo);
                if (remainingDays > 0)
                    resp.setTooltip(I18N.getLabel("app.user.expiring", remainingDays));
                IdentityUtils.log(cc, dao);
                return resp;
            } catch (Exception ex) {
                ((ISubject) SecurityUtils.getSubject()).setAuthenticate(false);
                return MessageUtils
                        .userAuthorizationError(userInfo.getId(), ex);
            }
        } else {
            ((ISubject) SecurityUtils.getSubject()).setAuthenticate(false);
            cc.setUser(null);
            return new SimpleResponseMessage();
        }
    }

    @Override
    public String getName() {
        return "login.Confirm";
    }
}
